{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 列表\n",
    "\n",
    "序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置，或索引，第一个索引是0，第二个索引是1，依此类推。\n",
    "\n",
    "Python有6个序列的内置类型，但最常见的是列表和元组。\n",
    "\n",
    "序列都可以进行的操作包括索引，切片，加，乘，检查成员。\n",
    "\n",
    "此外，Python已经内置确定序列的长度以及确定最大和最小的元素的方法。\n",
    "\n",
    "列表是最常用的Python数据类型，它可以作为一个方括号内的逗号分隔值出现。\n",
    "\n",
    "列表的数据项不需要具有相同的类型\n",
    "\n",
    "创建一个列表，只要把逗号分隔的不同的数据项使用方括号括起来即可。如下所示：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list1 = ['Google', 'Python', 1997, 2000]\n",
    "list2 = [1, 2, 3, 4, 5 ]\n",
    "list3 = [\"'a'\", \"b\", \"c\", \"d\",list2]\n",
    "print(list1,list2,list3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用下标索引来访问列表中的值，同样大家也可以使用方括号的形式截取字符，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list1[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list2[1:4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习1\n",
    "\n",
    "输出 “3” "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_list1 = [1,2,3,4,5]\n",
    "my_list2 = ['a',-1,0,4]\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更新列表\n",
    "我们可以对列表的数据项进行修改或更新，我们也可以使用append()方法来添加列表项，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list1 = ['Google', 'Python', 1997, 2000]\n",
    "print(\"第三个元素为 : \", list1[2])\n",
    "list1[2] = 2001\n",
    "print(\"更新后的第三个元素为 : \", list1[2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 删除列表元素\n",
    "可以使用 del 语句来删除列表的的元素，如下实例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list4 = ['Google', 'Python', 1997, 2000] \n",
    "print (\"原始列表 : \", list4)\n",
    "del list4[2]\n",
    "print (\"删除第三个元素 : \", list4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "list4 = ['Google', 'Python', 1997, 2000]\n",
    "list4.remove('Google')\n",
    "print (\"删除特定元素 : \", list4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习2\n",
    "把列表中不同类删掉，或替换另一种类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_list1 = ['苹果','华为','荔枝','芒果','西瓜']\n",
    "my_list2 = ['苹果','华为','三星','小米','西瓜']\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#-- 常用列表常量和操作，需要逐个运行，这里是展示\n",
    "L = [[1, 2], 'string', {}]                        # 嵌套列表\n",
    "L = list('spam')                                  # 列表初始化\n",
    "L = list(range(0, 4))                             # 列表初始化\n",
    "len(L)                                            # 求列表长度\n",
    "L.count(value)                                    # 求列表中某个值的个数\n",
    "L.append(obj)                                     # 向列表的尾部添加数据，比如append(2)，添加元素2\n",
    "L.insert(index, obj)                              # 向列表的指定index位置添加数据，index及其之后的数据后移\n",
    "L.extend(interable)                               # 通过添加iterable中的元素来扩展列表，比如extend([2])，添加元素2，注意和append的区别\n",
    "L.index(value, [start, [stop]])                   # 返回列表中值value的第一个索引\n",
    "L.pop([index])                                    # 删除并返回index处的元素，默认为删除并返回最后一个元素\n",
    "L.remove(value)                                   # 删除列表中的value值，只删除第一次出现的value的值\n",
    "L.reverse()                                       # 反转列表\n",
    "L.sort(cmp=None, key=None, reverse=False)         # 排序列表\n",
    "a = [1, 2, 3], b = a[10:]                         # 注意，这里不会引发IndexError异常，只会返回一个空的列表[]\n",
    "a = [], a += [1]                                  # 这里实在原有列表的基础上进行操作，即列表的id没有改变\n",
    "a = [], a = a + [1]                               # 这里最后的a要构建一个新的列表，即a的id发生了变化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#　L.sort(cmp=None, key=None, reverse=False)         # 排序列表\n",
    "L = [4,5,2,3,1,3,7]\n",
    "L.sort()\n",
    "print(L)\n",
    "L.reverse()\n",
    "print(L)\n",
    "print(L.count(788))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 列表解析\n",
    "列表解析的语法：[expr for iter_val in iterable] \n",
    "\n",
    "\n",
    "简单说，就是对于一个可迭代的对象中的每一个元素，通过表达式对该元素作用，得到一个计算结果，然后再通过for循环遍历这个可迭代对象的每一个元素，将作用后的结果构成一个列表。这个作用后的结果可能是由之前元素计算得到的新对象，也可能就是原先的元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 依次对序列中的每一个值实施计算\n",
    "a = [1, 2, 3, 4, 5]\n",
    "result = [x ** 2 for x in a] # x是元素，列表a是可迭代对象\n",
    "print(result) # >>> [1, 4, 9, 16, 25]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = [x + 1 for x in range(10)]\n",
    "print(result) # >>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = []\n",
    "for x in range(10):\n",
    "    result.append(x+1)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习3\n",
    "\n",
    "把大于100的数删掉，并且按从小到大排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_list1 = [6,7,88,191,32,330,12,54,901,104,3,67,111,1479,0]\n",
    "#解法1：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_list1 = [6,7,88,191,32,330,12,54,901,104,3,67,111,1479,0]\n",
    "#解法2：\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 元组\n",
    "Python 的元组与列表类似，不同之处在于元组的元素<strong>不能修改</strong>。\n",
    "\n",
    "元组使用小括号，列表使用方括号。\n",
    "\n",
    "元组创建很简单，只需要在括号中添加元素，并使用逗号隔开即可"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tup1 = ('Google', 'Python', 1997, 2000);\n",
    "tup2 = (1, 2, 3, 4, 5 );\n",
    "tup3 = \"a\", \"b\", \"c\", \"d\";   #  不需要括号也可以\n",
    "print(tup1,tup2,tup3)\n",
    "print(type(tup3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tup1 = ('Google', '[Python]', 1997, 2000)\n",
    "tup2 = (1, 2, 3, 4, 5, 6, 7 )\n",
    " \n",
    "print (\"tup1[0]: \", tup1[0])\n",
    "print (\"tup2[1:5]: \", tup2[1:5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tup1 = (12, 34.56);\n",
    "tup2 = ('abc', 'xyz')\n",
    " \n",
    "# 以下修改元组元素操作是非法的。\n",
    "# tup1[0] = 100\n",
    " \n",
    "# 创建一个新的元组\n",
    "tup3 = tup1 + tup2;\n",
    "print(tup3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#元组中的元素值是不允许删除的，但我们可以使用del语句来删除整个元组，如下实例:\n",
    "tup = ('Google', 'Runoob', 1997, 2000)\n",
    " \n",
    "print (tup)\n",
    "del tup\n",
    "print (\"删除后的元组 tup : \")\n",
    "print (tup)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习4\n",
    "\n",
    "用元组记录坐标(1,1),(2,2),(3,3),(4,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 提示：for循环解答\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 字典\n",
    "字典是另一种可变容器模型，且可存储任意类型对象。\n",
    "\n",
    "字典的每个键值(key=>value)对用冒号(:)分割，每个对之间用逗号(,)分割，整个字典包括在花括号({})中 ,格式如下所示\n",
    "\n",
    "d = {key1 : value1, key2 : value2 }\n",
    "\n",
    "键必须是唯一的，但值则不必。\n",
    "\n",
    "值可以取任何数据类型，但键必须是不可变的，如字符串，数字或元组。\n",
    "\n",
    "一个简单的字典实例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 把相应的键放入到方括号中，如下实例:\n",
    "dict1 = {'Name': 'Andy', 'Age': 7, 'Class': 'First'}\n",
    " \n",
    "print (\"dict1['Name']: \", dict1['Name'])\n",
    "print (\"dict1['Age']: \", dict1['Age'])\n",
    "\n",
    "dict1['Age'] = 8               #更新Age\n",
    "dict1['School'] = \"魔法学院\"    #添加信息\n",
    "print(dict1)\n",
    "# 向字典添加新内容的方法是增加新的键/值对，修改或删除已有键/值对如下实例:\n",
    "print (\"dict1['Age']: \", dict1['Age'])\n",
    "print (\"dict1['School']: \", dict1['School'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#-- 常用字典常量和操作，这里不能直接运行\n",
    "D = {}\n",
    "D = {'spam':2, 'tol':{'ham':1}}                   # 嵌套字典\n",
    "D = dict.fromkeys(['s', 'd'], 8)                  # {'s': 8, 'd': 8}\n",
    "D = dict(name = 'tom', age = 12)                  # {'age': 12, 'name': 'tom'}\n",
    "D = dict([('name', 'tom'), ('age', 12)])          # {'age': 12, 'name': 'tom'}\n",
    "D = dict(zip(['name', 'age'], ['tom', 12]))       # {'age': 12, 'name': 'tom'}\n",
    "D.keys(); D.values(); D.items()                   # 字典键、值以及键值对\n",
    "D.get(key, default)                               # get函数\n",
    "D.update(D_other)                                 # 合并字典，如果存在相同的键值，D_other的数据会覆盖掉D的数据\n",
    "D.pop(key, [D])                                   # 删除字典中键值为key的项，返回键值为key的值，如果不存在，返回默认值D，否则异常\n",
    "D.popitem()                                       # pop字典中随机的一项（一个键值对）\n",
    "del D                                             # 删除字典\n",
    "del D['key']                                      # 删除字典的某一项\n",
    "if key in D:   if key not in D:                   # 测试字典键是否存在\n",
    "# 字典注意事项：（1）对新索引赋值会添加一项（2）字典键不一定非得是字符串，也可以为任何的不可变对象\n",
    "# 不可变对象：调用对象自身的任意方法，也不会改变该对象自身的内容，这些方法会创建新的对象并返回。\n",
    "# 字符串、整数、tuple都是不可变对象，dict、set、list都是可变对象\n",
    "D[(1,2,3)] = 2                                    # tuple作为字典的key"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# 尝试一下\n",
    "D = {'spam':2, 'tol':{'ham':1}}  \n",
    "print(D)\n",
    "D_other = {'update':'new value'}\n",
    "D.update(D_other)\n",
    "print(D)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习5\n",
    "\n",
    "输出学生的年龄"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "student = {'名字':'莱克', '年龄':'12', '班级':'201', '性别':'男'}\n",
    "print(???)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 练习6\n",
    "\n",
    "新学期开始，需要更新所有学生的年龄，所有人年龄都加一岁。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "student_list=[\n",
    "    {'名字':'莱克', '年龄':'12', '班级':'201', '性别':'男'},\n",
    "    {'名字':'欣欣', '年龄':'12', '班级':'202', '性别':'女'},\n",
    "    {'名字':'紫琪', '年龄':'12', '班级':'202', '性别':'女'},\n",
    "    {'名字':'浩然', '年龄':'12', '班级':'201', '性别':'男'},\n",
    "    {'名字':'曹军', '年龄':'12', '班级':'202', '性别':'男'},\n",
    "    {'名字':'倩倩', '年龄':'12', '班级':'201', '性别':'女'}\n",
    "] \n",
    "for student in student_list:\n",
    "    student['年龄'] = ???\n",
    "    print(student)\n",
    "# print(student_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 集合\n",
    "集合（set）是一个<strong>无序不重复元素</strong>的序列。\n",
    "\n",
    "可以使用大括号 { } 或者 set() 函数创建集合，注意：创建一个空集合必须用 set() 而不是 { }，因为 { } 是用来创建一个空字典。\n",
    "\n",
    "创建格式："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}\n",
    "print(basket)                      # 这里演示的是去重功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#-- 集合set，不能直接运行\n",
    "\"\"\"\n",
    "set是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素。\n",
    "set支持union(联合), intersection(交), difference(差)和symmetric difference(对称差集)等数学运算。\n",
    "set支持x in set, len(set), for x in set。\n",
    "set不记录元素位置或者插入点, 因此不支持indexing, slicing, 或其它类序列的操作\n",
    "\"\"\"\n",
    "s = set([3,5,9,10])                          # 创建一个数值集合，返回{3, 5, 9, 10}\n",
    "t = set(\"Hello\")                             # 创建一个字符的集合，返回{'l', 'H', 'e', 'o'}\n",
    "a = t | s;    t.union(s)                     # t 和 s的并集\n",
    "b = t & s;    t.intersection(s)              # t 和 s的交集\n",
    "c = t - s;  t.difference(s)                # 求差集（项在t中, 但不在s中）\n",
    "d = t ^ s;    t.symmetric_difference(s)      # 对称差集（项在t或s中, 但不会同时出现在二者中）\n",
    "t.add('x');   t.remove('H')                  # 增加/删除一个item\n",
    "s.update([10,37,42])                         # 利用[......]更新s集合\n",
    "'x' in s,  'x' not in s                          # 集合中是否存在某个值\n",
    "s.issubset(t);      s <= t                   # 测试是否 s 中的每一个元素都在 t 中\n",
    "s.issuperset(t);    s >= t                   # 测试是否 t 中的每一个元素都在 s 中 \n",
    "s.copy(); \n",
    "s.discard('x');                                # 删除s中x\n",
    "s.clear()                                    # 清空s\n",
    "{x**2 for x in [1, 2, 3, 4]}                 # 集合解析，结果：{16, 1, 4, 9}\n",
    "{x for x in 'spam'}                          # 集合解析，结果：{'a', 'p', 's', 'm'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "set([3,3,5,9,10]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 尝试一下\n",
    "a = set(\"Hello\")\n",
    "b = set(\"Happy\")  \n",
    "print(a | b)\n",
    "print(a - b)\n",
    "a.add('x')\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  练习7\n",
    "\n",
    "题目：求s=a+aa+aaa+aaaa+aa...a的值，其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = int(input('有多少个数'))\n",
    "a = input('a代表数字是？')\n",
    "sn = [] # 记录相加的数字,sn = sum of number\n",
    "\n",
    "for count in range(？, ？？):  #count 数数\n",
    "    tmp_a = a*count   #tmp = template 临时\n",
    "   ？？？\n",
    "print(sn)\n",
    "print('+'.join([str(s)for s in sn])) # 输出算式，（可以不写）.join字符串专用\n",
    "# Sn 求和\n",
    "sum(sn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'2'*2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 扩展知识\n",
    "\n",
    "collections是Python内建的一个集合模块，提供了许多有用的集合类。\n",
    "\n",
    "1. namedtuple\n",
    "2. deque\n",
    "3. defaultdict\n",
    "4. OrderedDict\n",
    "5. Counter\n",
    "\n",
    "更多解释，我们可以网上找一下用法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### namedtuple\n",
    "\n",
    "它用来创建一个自定义的tuple对象，并且规定了tuple元素的个数，并可以用属性而不是索引来引用tuple的某个元素。\n",
    "\n",
    "这样一来，我们用namedtuple可以很方便地定义一种数据类型，它具备tuple的不变性，又可以根据属性来引用，使用十分方便。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import namedtuple\n",
    "Point = namedtuple('Point', ['x', 'y'])\n",
    "p = Point(1, 2)  #nametuple的作用：让元组像字典一样，能带键值表示，不用索引\n",
    "print(p.x, p.y)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### deque\n",
    "使用list存储数据时，按索引访问元素很快，但是插入和删除元素就很慢了，因为list是线性存储，数据量大的时候，插入和删除效率很低。\n",
    "\n",
    "deque是为了高效实现插入和删除操作的双向列表，适合用于队列和栈："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import deque\n",
    "q = deque(['a', 'b', 'c'])\n",
    "q.append('x')\n",
    "q.appendleft('y')\n",
    "print(q)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### defaultdict\n",
    "使用dict时，如果引用的Key不存在，就会抛出KeyError。如果希望key不存在时，返回一个默认值，就可以用defaultdict："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import defaultdict\n",
    "dd = defaultdict(list)\n",
    "dd['key1'] = 'abc'\n",
    "print(dd['key1']) # key1存在\n",
    "print(dd['key2']) # key2不存在，返回默认值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### OrderedDict\n",
    "使用dict时，Key是无序的。在对dict做迭代时，我们无法确定Key的顺序。\n",
    "\n",
    "如果要保持Key的顺序，可以用OrderedDict："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import OrderedDict\n",
    "d = {'a': 1, 'b': 2, 'c': 3}\n",
    "print('无序的', d) # dict的Key是无序的\n",
    "od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])\n",
    "print(od)\n",
    "od.move_to_end('a')\n",
    "print(od)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "默认情况下Python的字典输出顺序是按照键的按创建顺序。\n",
    "\n",
    "字典的无序是指，不能人为重新排序。\n",
    "\n",
    "比如说你按键值1，2，3，4的顺序创建的字典，只能由解析器按创建顺序，还是1，2，3，4的输出。\n",
    "\n",
    "你无法控制它按照，4，3，2，1的顺序输出，你也无法做到，1，3，2，4的顺序。\n",
    "\n",
    "而且这个输出顺序是也不是能真正按照创建顺序可以控的。\n",
    "\n",
    "这里面有两个影响因素：\n",
    "\n",
    "（1）键值的哈希碰撞，hash(key1) == hash(key2)时，向字典里连续添加的这两个键的顺序是不可以控制的，也是无法做到连续的，后来的键会按算法调整到其它位置\n",
    "\n",
    "（2）字典空间扩容，当键的数量超过字典默认开的空间时，字典会做空间扩容，扩容后的键顺和创建顺序就会发生变化，不受人为控制"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Counter\n",
    "Counter是一个简单的计数器，例如，统计字符出现的个数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import Counter  #说明要使用这个函数，这个函数不是默认就能用，collection是一个代码库\n",
    "c = Counter()   #Counter()是对象，后面会详细说\n",
    "for ch in 'programming':  #用for循环遍历整个字符串\n",
    "    c[ch] = c[ch] + 1\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 练习"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 查找列表中元素，查找以A或a开头并且以c结尾的所有元素\n",
    "li = ['alec','aric','Alex',' Tony','rain']\n",
    "tu = ('alec','aric','Alex',' Tony','rain')\n",
    "dic = {'k1':'alex','k2':'aric','k3':'Alex','k4':'Tony'}\n",
    "\n",
    "for val in li:\n",
    "    val = val.lower()\n",
    "    if val.startswith('a') and val.endswith('c'):  #startswith 和 endswith 是字符串自带的固定写法\n",
    "        print(val, end=',')\n",
    "        \n",
    "print('\\n----------------------------------')\n",
    "\n",
    "for val in tu:\n",
    "    ？？？\n",
    "    ？？？\n",
    "    ？？？\n",
    "        \n",
    "print('\\n----------------------------------')\n",
    "\n",
    "for val in dic.values():\n",
    "    ？？？\n",
    "    ？？？\n",
    "    ？？？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "states = { '广东': '粤',\n",
    "    '福建': '闽',\n",
    "    '湖北': '鄂',}\n",
    "\n",
    "cities = {'粤': '佛山',\n",
    "    '鄂': '武汉',}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "添加城市 闽：厦门"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 解答\n",
    "cities['闽'] = '厦门'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "打印所有states"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "广东:粤\n",
      "福建:闽\n",
      "湖北:鄂\n"
     ]
    }
   ],
   "source": [
    "for key, val in states.items():\n",
    "    print(key + \":\" + val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "打印所有cities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "粤:佛山\n",
      "鄂:武汉\n",
      "闽:厦门\n"
     ]
    }
   ],
   "source": [
    "for key, val in ???():\n",
    "    print(key + \":\" + val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 打印所有states，以及states 包含的cities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "广东:粤\n",
      "     |- 佛山\n",
      "福建:闽\n",
      "     |- 厦门\n",
      "湖北:鄂\n",
      "     |- 武汉\n"
     ]
    }
   ],
   "source": [
    "for key, val in states.items():\n",
    "    print(key + \":\" + val)\n",
    "\n",
    "    if val in cities.keys():\n",
    "        print(\"     |-\",cities[val])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cities.keys()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
